package web

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"net/http"
	"sort"
	"strings"
	"sync"
	"time"

	"ssh_status/internal/v2/stats" // 使用完整路径导入stats包

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/ssh"
)

// healthCheck 健康检查API
func (s *Server) healthCheck(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"status":  "ok",
		"version": "1.0.0",
	})
}

// detectSSHConnection SSH连接检测API
func (s *Server) detectSSHConnection(c *gin.Context) {
	// 解析POST请求参数
	var req struct {
		Network  string `json:"network" binding:"required"`
		Port     int    `json:"port" binding:"required"`
		Username string `json:"username" binding:"required"`
		Password string `json:"password" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "参数错误: " + err.Error(),
		})
		return
	}

	// 设置SSE响应头
	c.Header("Content-Type", "text/event-stream")
	c.Header("Cache-Control", "no-cache")
	c.Header("Connection", "keep-alive")
	c.Header("Transfer-Encoding", "chunked")

	// 创建一个通道用于发送进度消息
	progressChan := make(chan interface{})
	defer close(progressChan)

	// 启动一个goroutine来执行扫描
	go func() {
		// 发送开始消息
		progressChan <- gin.H{
			"type":    "start",
			"message": fmt.Sprintf("开始扫描任务 - 网段: %s, 端口: %d, 用户名: %s", req.Network, req.Port, req.Username),
		}

		// 解析CIDR网段
		_, ipnet, err := net.ParseCIDR(req.Network)
		if err != nil {
			progressChan <- gin.H{
				"type":    "error",
				"message": "无效的CIDR格式: " + err.Error(),
			}
			return
		}

		// 获取所有IP地址
		ips := make([]string, 0)
		for ip := ipnet.IP.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
			ips = append(ips, ip.String())
		}

		total := len(ips)
		if total == 0 {
			progressChan <- gin.H{
				"type":    "error",
				"message": "网段中没有可用的IP地址",
			}
			return
		}

		// 创建任务通道
		taskChan := make(chan string, total)
		resultChan := make(chan gin.H, total)
		var wg sync.WaitGroup

		// 启动工作协程（默认10个并发）
		for i := 0; i < 10; i++ {
			wg.Add(1)
			go func() {
				defer wg.Done()
				for ip := range taskChan {
					// 尝试SSH连接
					result := trySSHConnection(ip, req.Port, req.Username, req.Password)
					resultChan <- result
				}
			}()
		}

		// 发送任务
		go func() {
			for _, ip := range ips {
				taskChan <- ip
			}
			close(taskChan)
		}()

		// 收集结果
		var results []gin.H
		completed := 0
		lastProgress := -1

		// 启动结果收集协程
		go func() {
			for result := range resultChan {
				results = append(results, result)
				completed++

				// 计算进度
				progress := int(float64(completed) / float64(total) * 100)

				// 只在进度变化时发送更新
				if progress != lastProgress {
					lastProgress = progress
					progressChan <- gin.H{
						"type":     "progress",
						"progress": progress,
						"current":  completed,
						"total":    total,
						"message":  fmt.Sprintf("正在扫描: %d/%d", completed, total),
					}
				}
			}
		}()

		// 等待所有任务完成
		wg.Wait()
		close(resultChan)

		// 对结果按IP地址排序
		sort.Slice(results, func(i, j int) bool {
			ip1 := net.ParseIP(results[i]["ip"].(string))
			ip2 := net.ParseIP(results[j]["ip"].(string))
			if ip1 == nil || ip2 == nil {
				return false
			}
			return bytes.Compare(ip1, ip2) < 0
		})

		// 发送完成消息
		stats := stats.CalcScanStats(results)
		s.Stats = stats // 直接更新Server的统计数据
		progressChan <- gin.H{
			"type":      "complete",
			"progress":  100,
			"current":   total,
			"total":     total,
			"message":   fmt.Sprintf("扫描完成，共扫描 %d 个IP地址", total),
			"results":   results,
			"stats":     stats,
			"status":    "complete",
			"port_open": true,
		}
	}()

	// 发送SSE消息
	c.Stream(func(w io.Writer) bool {
		if msg, ok := <-progressChan; ok {
			// 将消息转换为JSON
			jsonData, err := json.Marshal(msg)
			if err != nil {
				return false
			}
			// 发送SSE消息
			c.SSEvent("message", string(jsonData))
			return true
		}
		return false
	})
}

// trySSHConnection 尝试SSH连接
func trySSHConnection(ip string, port int, username, password string) gin.H {
	// 先检查端口状态
	conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), 5*time.Second)
	if err != nil {
		return gin.H{
			"ip":         ip,
			"port":       port,
			"status":     "port_closed",
			"message":    "端口未开启",
			"username":   username,
			"connected":  false,
			"root":       false,
			"port_open":  false,
			"auth_state": "none",
		}
	}
	conn.Close()

	// 端口已开启，尝试SSH连接
	config := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		Timeout:         5 * time.Second,
	}

	client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", ip, port), config)
	if err != nil {
		if strings.Contains(err.Error(), "ssh: unable to authenticate") {
			return gin.H{
				"ip":         ip,
				"port":       port,
				"status":     "auth_failed",
				"message":    "认证失败",
				"username":   username,
				"connected":  false,
				"root":       false,
				"port_open":  true,
				"auth_state": "failed",
			}
		}
		return gin.H{
			"ip":         ip,
			"port":       port,
			"status":     "error",
			"message":    err.Error(),
			"username":   username,
			"connected":  false,
			"root":       false,
			"port_open":  true,
			"auth_state": "error",
		}
	}
	defer client.Close()

	// 检查root权限
	session, err := client.NewSession()
	if err != nil {
		return gin.H{
			"ip":         ip,
			"port":       port,
			"status":     "connected",
			"message":    "连接成功",
			"username":   username,
			"connected":  true,
			"root":       false,
			"port_open":  true,
			"auth_state": "success",
		}
	}
	defer session.Close()

	// 检查是否是root用户
	var isRoot bool
	output, err := session.Output("id -u")
	if err == nil && string(output) == "0\n" {
		isRoot = true
	}

	// 检查sudo权限
	err = session.Run("sudo -n true")
	if err == nil {
		return gin.H{
			"ip":         ip,
			"port":       port,
			"status":     "sudo_supported",
			"message":    "支持sudo",
			"username":   username,
			"connected":  true,
			"root":       isRoot,
			"port_open":  true,
			"auth_state": "success",
			"sudo":       true,
		}
	}

	return gin.H{
		"ip":         ip,
		"port":       port,
		"status":     "connected",
		"message":    "连接成功",
		"username":   username,
		"connected":  true,
		"root":       isRoot,
		"port_open":  true,
		"auth_state": "success",
		"sudo":       false,
	}
}

// inc 增加IP地址
func inc(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

// getStats 返回当前扫描统计信息
func (s *Server) getStats(c *gin.Context) {
	// 获取当前统计数据
	stats := s.Stats
	c.JSON(200, gin.H{
		"stats": stats,
	})
}
